import { FC, useCallback, useState } from 'react';
import { message, Modal, Tooltip, Upload as AntdUpload, Typography, Row } from 'antd';
import {
  RcFile,
  UploadChangeParam,
  UploadFile,
  UploadProps as AntdUploadProps
} from 'antd/lib/upload/interface';
import _ from 'lodash';

import { Content, Header } from '@/components/Page';
import Icons from '@/components/Icons';

import { COMMON_IMG_ALT } from '@/utils/config';
import { downloadFile, fileToBase64String } from '@/utils/util';
import { PictureSuffixList, UploadFileSuffix } from '@/enumTypes/upload';

import styles from './index.module.less';

const { Text, Link } = Typography;

export interface UploadProps extends AntdUploadProps {
  /** 单文件上传限制大小(单位为MB) */
  singleFileMaxSize?: number;
}

const Upload: FC<UploadProps> = ({ accept, maxCount, singleFileMaxSize, ...rest }) => {
  const [fileList, setFileList] = useState<UploadFile[]>([]);
  const [previewOpen, setPreviewOpen] = useState<boolean>(false);
  const [previewData, setPreviewData] = useState<string>('');
  const [previewTitle, setPreviewTitle] = useState<string>('');
  const [isPicture, setIsPicture] = useState<boolean>(true);

  /** 文件变更 */
  const handleChange: AntdUploadProps['onChange'] = useCallback(
    (fileInfo: UploadChangeParam) => {
      console.log('改变', fileInfo);
      let newFileList = [...fileInfo.fileList];

      // 限制文件上传数量并且用最新的替换旧的
      if (_.isNumber(maxCount)) newFileList = newFileList.slice(-maxCount);

      setFileList(newFileList);
    },
    [maxCount]
  );

  /** 上传前异步校验(可进行服务端校验) */
  const handleBeforeUpload = useCallback(
    (file: RcFile) => {
      // 文件类型校验
      const fileSuffix = file.name.slice(file.name.lastIndexOf('.'));
      const isFileTypeExceeded = accept ? !accept.split(',').includes(fileSuffix) : false;
      if (isFileTypeExceeded) {
        message.error(`你只能上传${accept}文件！`);
      }

      // 文件大小校验
      const isFileSizeExceeded = singleFileMaxSize
        ? file.size > singleFileMaxSize * 1024 * 1024
        : false;
      if (isFileSizeExceeded) {
        message.error(`文件大小不能超过${singleFileMaxSize}MB！`);
      }

      return (!isFileTypeExceeded && !isFileSizeExceeded) || AntdUpload.LIST_IGNORE;
    },
    [accept, singleFileMaxSize]
  );

  /** 预览 */
  const handlePreview = useCallback(
    async (file: UploadFile) => {
      if (!file.url && !file.preview) {
        file.preview = await fileToBase64String(file.originFileObj as RcFile);
      }

      // 预览文件类型
      const fileSuffix = file.name.slice(file.name.lastIndexOf('.'));

      // 设置当前预览数据
      setIsPicture(PictureSuffixList.includes(fileSuffix as UploadFileSuffix));
      setPreviewData(file.url || (file.preview as string));
      setPreviewTitle(file.name || file.url?.substring(file.url?.lastIndexOf('/') + 1) || '');
      setPreviewOpen(true);
    },
    [fileList]
  );

  /** 预览前构成预览url */
  const handleBeforePreview: (file: File | Blob) => PromiseLike<string> = useCallback(
    async (file: File | Blob) => {
      const thumbUrl = await fileToBase64String(file as RcFile);
      return Promise.resolve(thumbUrl);
    },
    []
  );

  /** 下载 */
  const handleDownload = useCallback(({ thumbUrl, name }: UploadFile) => {
    if (thumbUrl) downloadFile(thumbUrl, name);
  }, []);

  /** 删除 */
  const handleRemove = useCallback(async (file: UploadFile) => {
    console.log('删除', file);
    return Promise.resolve(true);
  }, []);

  console.log(fileList);

  return (
    <>
      <Header title="附件上传" backPath="/test-pages" />
      <Content>
        <AntdUpload
          action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
          listType="picture-card"
          className={styles.rbUpload}
          fileList={fileList}
          showUploadList={{
            showPreviewIcon: true,
            showDownloadIcon: true,
            showRemoveIcon: true
          }}
          multiple
          progress={{
            strokeColor: {
              '0%': '#108ee9',
              '100%': '#87d068'
            },
            strokeWidth: 3,
            format: percent =>
              percent && <span style={{ fontSize: 8 }}>{parseFloat(percent.toFixed(2))}%</span>
          }}
          onChange={handleChange}
          beforeUpload={handleBeforeUpload}
          onPreview={handlePreview}
          previewFile={handleBeforePreview}
          onDownload={handleDownload}
          onRemove={handleRemove}
          {...rest}
        >
          <div className={styles.rbUploadButtonWapper}>
            <Icons className={styles.rbUploadButtonIcons} type="FolderFilled" />
            <Tooltip
              color="white"
              title={accept ? <div style={{ color: 'black' }}>{accept}</div> : null}
            >
              <div className={styles.rbUploadButtonText}>点击或将文件拖拽至此处上传</div>
            </Tooltip>
          </div>
        </AntdUpload>
        <Modal
          open={previewOpen}
          title={previewTitle}
          footer={null}
          onCancel={() => setPreviewOpen(false)}
        >
          {isPicture ? (
            <img alt={COMMON_IMG_ALT} style={{ width: '100%' }} src={previewData} />
          ) : (
            <Row justify="space-between">
              <Text type="danger">该文件格式暂不支持预览</Text>
              <Link
                onClick={() =>
                  handleDownload({ thumbUrl: previewData, name: previewTitle, uid: '' })
                }
              >
                点击下载
              </Link>
            </Row>
          )}
        </Modal>
      </Content>
    </>
  );
};

export default Upload;
